package org.hackystat.sdsa.analyzer.control.processor;

import java.util.logging.Logger;

import javax.xml.datatype.XMLGregorianCalendar;

import org.hackystat.sdsa.analyzer.model.activity.Activity;
import org.hackystat.sdsa.analyzer.model.activity.edit.DocumentEditActivity;
import org.hackystat.sdsa.analyzer.model.activity.edit.EditActivity;
import org.hackystat.sdsa.analyzer.model.activity.edit.ProductionEditActivity;
import org.hackystat.sdsa.analyzer.model.activity.edit.UnitTestEditActivity;
import org.hackystat.sensorbase.resource.sensordata.jaxb.Properties;
import org.hackystat.sensorbase.resource.sensordata.jaxb.Property;
import org.hackystat.sensorbase.resource.sensordata.jaxb.SensorData;
import org.hackystat.utilities.tstamp.Tstamp;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

/**
 * Test EditActivityProcessor.
 * 
 * @author hongbing
 *
 */
public class TestEditActivityProcessor {
  /** Edit activity processor */
  private EditActivityProcessor processor;
  private Logger logger;
  
  /**
   * Prepares test variables.
   * 
   * @throws Exception If error in testing. 
   */
  @Before public void setUp() throws Exception {
    this.processor = new EditActivityProcessor();
    this.logger = Logger.getLogger(TestEditActivityProcessor.class.getName());
  }
  
  
  /**
   * Test the processor of edit activity.
   * 
   * @throws Exception If error occurs
   */
  @Test public void testDocument() throws Exception {
    /** Document edit data. */
    SensorData docEditData = new SensorData();
    XMLGregorianCalendar tstamp = Tstamp.makeTimestamp("2007-11-17T10:25:16.949-08:00");
    docEditData.setTimestamp(tstamp);
    docEditData.setResource("file:/C:/cvs/work/com/foo/jboss-config.xml");
    docEditData.setSensorDataType("DevEvent");
    
    Properties props = new Properties();
    Property type = new Property();
    type.setKey("Type");
    type.setValue("Edit");
    props.getProperty().add(type);
    
    Property subType = new Property();
    subType.setKey("Subtype");
    subType.setValue("StateChange");
    props.getProperty().add(subType);
    
    Property currentSize = new Property();
    currentSize.setKey(EditActivity.CURRENT_SIZE);
    currentSize.setValue("300");
    props.getProperty().add(currentSize);
    
    docEditData.setProperties(props);
    
    assertTrue("Test processable of document edit activity", 
           this.processor.processable(docEditData));
    
    Activity baseActivity = this.processor.process(docEditData, this.logger);
    Assert.assertTrue("Check return type", baseActivity instanceof DocumentEditActivity);
    DocumentEditActivity activity = (DocumentEditActivity) baseActivity;
    assertNotNull("Test conversion from DevEvent to document edit activity", activity);
    
    assertEquals("Test file size", 300, activity.getFileSize());
  }


  /**
   * Test the processor of edit activity.
   * @throws Exception If error occurs
   */
  @Test public void testProduction() throws Exception {
    /** Production code edit data. */
    SensorData productEditData = new SensorData();
    XMLGregorianCalendar tstamp = Tstamp.makeTimestamp("2007-11-17T10:25:16.949-08:00");
    productEditData.setTimestamp(tstamp);
    productEditData.setResource("file:/C:/cvs/work/com/foo/Bar.java");
    productEditData.setSensorDataType("DevEvent");

    Properties props = new Properties();
    productEditData.setProperties(props);
    
    Property type = new Property();
    type.setKey("Type");
    type.setValue("Edit");
    props.getProperty().add(type);
    
    Property subType = new Property();
    subType.setKey("Subtype");
    subType.setValue("StateChange");
    props.getProperty().add(subType);
    
    Property currentSize = new Property();
    currentSize.setKey(EditActivity.CURRENT_SIZE);
    currentSize.setValue("1560");
    props.getProperty().add(currentSize);

    Property className = new Property();
    className.setKey(ProductionEditActivity.CLASS_NAME);
    className.setValue("com.foo.Bar");
    props.getProperty().add(className);

    Property currentStatements = new Property();
    currentStatements.setKey(ProductionEditActivity.CURRENT_STATEMENTS);
    currentStatements.setValue("36");
    props.getProperty().add(currentStatements);

    Property currentMethods = new Property();
    currentMethods.setKey(ProductionEditActivity.CURRENT_METHODS);
    currentMethods.setValue("2");
    props.getProperty().add(currentMethods);

    assertTrue("Test processable of document edit activity", 
           this.processor.processable(productEditData));
    
    Activity baseActivity = this.processor.process(productEditData, this.logger);
    assertTrue("Check return type", baseActivity instanceof ProductionEditActivity);
    ProductionEditActivity activity = (ProductionEditActivity) baseActivity;
    assertNotNull("Test conversion from DevEvent to production edit activity", activity);
    assertEquals("Test file size", 1560, activity.getFileSize());
    assertEquals("Test numOfMethods", 2, activity.getNumOfMethods());
    assertEquals("Test numOfStatements", 36, activity.getNumOfStatements());

    assertEquals("Test class name", "com.foo.Bar", activity.getClassName()); 
  }


  /**
   * Test the processor of edit activity.
   * 
   * @throws Exception If error occurs
   */
  @Test public void testUnitTesting() throws Exception {
    /** Unit test edit data. */
    SensorData testEditData = new SensorData();
    XMLGregorianCalendar tstamp = Tstamp.makeTimestamp("2007-11-17T10:28:16.005-08:00");
    testEditData.setTimestamp(tstamp);
    testEditData.setResource("file:/C:/cvs/work/com/foo/TestBar.java");
    testEditData.setSensorDataType("DevEvent");

    Properties props = new Properties();
    testEditData.setProperties(props);
    
    Property type = new Property();
    type.setKey("Type");
    type.setValue("Edit");
    props.getProperty().add(type);
    
    Property subType = new Property();
    subType.setKey("Subtype");
    subType.setValue("StateChange");
    props.getProperty().add(subType);
    
    Property currentSize = new Property();
    currentSize.setKey(EditActivity.CURRENT_SIZE);
    currentSize.setValue("1560");
    props.getProperty().add(currentSize);

    Property className = new Property();
    className.setKey(ProductionEditActivity.CLASS_NAME);
    className.setValue("com.foo.TestBar");
    props.getProperty().add(className);

    Property currentStatements = new Property();
    currentStatements.setKey(ProductionEditActivity.CURRENT_STATEMENTS);
    currentStatements.setValue("36");
    props.getProperty().add(currentStatements);

    Property currentMethods = new Property();
    currentMethods.setKey(ProductionEditActivity.CURRENT_METHODS);
    currentMethods.setValue("5");
    props.getProperty().add(currentMethods);

    Property currentTestMethods = new Property();
    currentTestMethods.setKey(UnitTestEditActivity.CURRENT_TEST_METHODS);
    currentTestMethods.setValue("3");
    props.getProperty().add(currentTestMethods);

    Property currentTestAssertions = new Property();
    currentTestAssertions.setKey(UnitTestEditActivity.CURRENT_TEST_ASSERTIONS);
    currentTestAssertions.setValue("8");
    props.getProperty().add(currentTestAssertions);

    
    assertTrue("Test processable of document edit activity", 
           this.processor.processable(testEditData));
    
    Activity baseActivity = this.processor.process(testEditData, this.logger);
    assertTrue("Check return type", baseActivity instanceof UnitTestEditActivity);
    UnitTestEditActivity activity = (UnitTestEditActivity) baseActivity;
    assertNotNull("Test conversion from DevEvent to production edit activity", activity);
    assertEquals("Test file size", 1560, activity.getFileSize());
    assertEquals("Test class name", "com.foo.TestBar", activity.getClassName());
    assertEquals("Test numOfMethods", 5, activity.getNumOfMethods());
    assertEquals("Test numOfStatements", 36, activity.getNumOfStatements());
    assertEquals("Test numOfTestMethods", 3, activity.getNumOfTestMethods());
    assertEquals("Test numOfTestAssertions", 8, activity.getNumOfTestAssertions());
  }

}